import type { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; import { Breadcrumbs } from "@/components/entity/breadcrumbs"; import { JsonLd } from "@/components/entity/json-ld"; import { Badge } from "@/components/ui/badge"; import { cn } from "@/components/ui/cn"; import { Card, CardBody, CardHeader, Page } from "@/components/ui/card"; import { LinkTabs } from "@/components/ui/tabs"; import { CoverageBar } from "@/components/intelligence/shared"; import { CountryFlag } from "@/components/ui/country-flag"; import { EmptyState, OfflineNotice } from "@/components/ui/states"; import { RowLink, TBody, THead, Table, Td, Th, Tr } from "@/components/ui/table"; import { api } from "@/lib/api"; import { fmtDate, fmtDelta, fmtInt, fmtPct } from "@/lib/format"; import type { SearchParams } from "@/lib/sort"; import { routes } from "@/lib/routes"; import { NOT_FOUND_METADATA, absoluteUrl, pageMetadata } from "@/lib/seo"; import { SCOPE_LABEL, firstSentence, fmtRankValue, rowHref, secondaryLabel } from "../ranking-format"; export const revalidate = 120; type Params = Promise<{ key: string }>; export async function generateMetadata({ params }: { params: Params }): Promise { const { key } = await params; const r = await api.ranking(key, { limit: 200 }); if (!r.ok) return r.status === 404 || r.status === 400 ? NOT_FOUND_METADATA : { title: "Ranking" }; const d = r.data; return pageMetadata({ title: d.label, description: `Ranking of ${SCOPE_LABEL[d.scope].toLowerCase()} by ${d.label.toLowerCase()} — ${d.unit}. ${firstSentence(d.methodology)}`, path: routes.ranking(d.key), }); } export default async function RankingPage({ params, searchParams }: { params: Params; searchParams: Promise }) { const [{ key }, sp] = await Promise.all([params, searchParams]); const mode = sp.mode === "all" ? "all" : "strict"; const r = await api.ranking(key, { limit: 200, mode }); if (!r.ok && (r.status === 404 || r.status === 400)) notFound(); if (!r.ok) { return ( ); } const d = r.data; const rows = d.rows ?? []; const showFlag = d.scope === "countries" || rows.some((x) => x.countryIso2); const hasSecondary = rows.some((x) => x.secondary !== null && x.secondary !== undefined); const hasCoverage = rows.some((x) => x.coverage !== null && x.coverage !== undefined); const hasDelta = rows.some((x) => x.delta !== null && x.delta !== undefined); const secLabel = secondaryLabel(d.methodology); const jsonLd = { "@context": "https://schema.org", "@type": "ItemList", name: d.label, description: firstSentence(d.methodology), url: absoluteUrl(routes.ranking(d.key)), numberOfItems: rows.length, itemListOrder: "https://schema.org/ItemListOrderDescending", itemListElement: rows.slice(0, 100).map((row) => ({ "@type": "ListItem", position: row.rank, name: row.name, url: absoluteUrl(rowHref(row, d.scope)) })), }; return (
Ranking · {SCOPE_LABEL[d.scope]}

{d.label}

{d.unit} {SCOPE_LABEL[d.scope]} Computed {fmtDate(d.computedAt)} {d.total > 0 && ( · {fmtInt(d.total)} {d.total === 1 ? "entity" : "entities"} )}
{d.minCoverage !== undefined && d.minCoverage !== null &&

Entities with fewer than 5 facilities or MW coverage below {fmtPct(d.minCoverage)} are excluded, not estimated.

}

Known / published figures only — entities without a figure are absent, not estimated.

{d.minCoverage !== undefined && d.minCoverage !== null && (

Strict = coverage gate applied (≥ 5 facilities, ≥ {fmtPct(d.minCoverage)} with a figure). All observed lists every entity with at least one published figure regardless of coverage; the coverage column shows how incomplete each row is. Nothing is estimated in either view.

)} {rows.length === 0 ? ( All rankings } /> ) : ( {hasSecondary && ( )} {hasCoverage && } {hasDelta && ( )} {rows.map((row) => ( {hasSecondary && ( )} {hasCoverage && ( )} {hasDelta && ( )} ))}
# {d.scope === "countries" ? "Country" : d.scope === "metros" ? "Market" : d.scope === "operators" ? "Operator" : "Facility"} {d.unit} {secLabel} Coverage Δ rank
{row.rank} {showFlag && row.countryIso2 && } {row.name} {fmtRankValue(row.value, d.unit)} {row.secondary === null || row.secondary === undefined ? "—" : fmtInt(row.secondary)} {row.coverage === null || row.coverage === undefined ? ( — ) : ( )} {row.delta === null || row.delta === undefined ? new : 0 ? "text-ok" : row.delta < 0 ? "text-danger" : "text-ink-3")}>{fmtDelta(row.delta)}}
)}

{d.methodology}

Values are lower bounds computed from published or filed figures only. Coverage is the share of an entity's facilities carrying any MW figure; a low coverage means the value understates reality.

Δ rank compares with the previous computation of the same ranking; “new” marks an entity that was not ranked before.

All rankings · Methodology

); }